// middleware/auth.go
package middleware

import (
	"errors"
	"net/http"
	"strings"
	"time"

	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

var (
	// ErrInvalidToken 表示无效的token
	ErrInvalidToken = errors.New("无效的认证令牌")
	// ErrTokenExpired 表示token已过期
	ErrTokenExpired = errors.New("认证令牌已过期")
)

// AuthConfig 包含认证中间件的配置
type AuthConfig struct {
	Logger     *zap.Logger
	SecretKey  string
	TokenValid time.Duration
}

// AuthMiddleware 创建一个JWT认证中间件
func AuthMiddleware(config AuthConfig) gin.HandlerFunc {
	return func(c *gin.Context) {
		// 从请求头中获取Authorization字段
		authHeader := c.GetHeader("Authorization")
		if authHeader == "" {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
				"code":    http.StatusUnauthorized,
				"message": "缺少认证信息",
			})
			return
		}

		// 验证Authorization格式
		parts := strings.Split(authHeader, " ")
		if len(parts) != 2 || parts[0] != "Bearer" {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
				"code":    http.StatusUnauthorized,
				"message": "认证格式错误",
			})
			return
		}

		// 解析JWT token
		tokenStr := parts[1]
		token, err := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {
			// 验证签名方法
			if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
				return nil, ErrInvalidToken
			}
			return []byte(config.SecretKey), nil
		})

		if err != nil {
			if ve, ok := err.(*jwt.ValidationError); ok {
				if ve.Errors&jwt.ValidationErrorExpired != 0 {
					c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
						"code":    http.StatusUnauthorized,
						"message": ErrTokenExpired.Error(),
					})
					return
				}
			}
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
				"code":    http.StatusUnauthorized,
				"message": ErrInvalidToken.Error(),
			})
			return
		}

		if !token.Valid {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
				"code":    http.StatusUnauthorized,
				"message": ErrInvalidToken.Error(),
			})
			return
		}

		// 从token中获取用户信息
		if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
			// 将用户ID存储到上下文中，以便后续处理使用
			userId, ok := claims["user_id"].(float64)
			if !ok {
				c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
					"code":    http.StatusUnauthorized,
					"message": "无效的用户信息",
				})
				return
			}
			c.Set("user_id", uint(userId))

			// 将角色ID存储到上下文中
			roleId, ok := claims["role_id"].(float64)
			if ok {
				c.Set("role_id", uint(roleId))
			}

			// 将用户名存储到上下文中
			username, ok := claims["username"].(string)
			if ok {
				c.Set("username", username)
			}
		} else {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
				"code":    http.StatusUnauthorized,
				"message": ErrInvalidToken.Error(),
			})
			return
		}

		// 继续处理请求
		c.Next()
	}
}
